package org.example.juc;

import com.sun.deploy.util.ReflectionUtil;
import sun.misc.Unsafe;

import java.io.File;
import java.io.FileNotFoundException;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.LockSupport;

public class AQSCLHLock implements Lock {

    /**
     * 锁的状态：
     *  0：初始化或者没有锁被占用
     *  1：锁被占用
     */
    private volatile int state;

    private final Long stateAddress;

    private final Node EMPTY_NODE = new Node();

    private volatile Node head;
    private final Long headAddress;

    private volatile Node tail;
    private final Long tailAddress;

    /**
     * 占有锁的线程
     */
    private Thread currentThread;

    private final Unsafe unsafe;

    public AQSCLHLock() {
        try {
            Class unsafeClass = ReflectionUtil.getClass("sun.misc.Unsafe", Thread.currentThread().getContextClassLoader());
            Method getUnsafeMethod = unsafeClass.getDeclaredMethod("getUnsafe", null);
            this.unsafe  = (Unsafe) getUnsafeMethod.invoke(null, new Object[]{});

            Field stateField = this.getClass().getField("state");
            stateAddress =  this.unsafe.objectFieldOffset(stateField);

            Field headField = this.getClass().getField("head");
            headAddress = this.unsafe.objectFieldOffset(headField);
            Field tailField = this.getClass().getField("tail");
            tailAddress = this.unsafe.objectFieldOffset(tailField);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void lock() {
        if (!tryLock()) {
            Node node = addWaiter();
            // 考虑前驱节点进行自旋
            acquireQueued(node);
        }
    }

    @Override
    public void lockInterruptibly() throws InterruptedException {

    }

    @Override
    public boolean tryLock() {
        if (casSwapState(0, 1)) {
            currentThread = Thread.currentThread();
            return true;
        }
        return false;
    }

    @Override
    public boolean tryLock(long time, TimeUnit unit) throws InterruptedException {
        return false;
    }

    @Override
    public void unlock() {
        Thread thread = Thread.currentThread();
        if (thread != currentThread) {
            throw new RuntimeException("只有站有所的线程才能释放锁");
        }

        setCurrentThread(null);
        setState(0);

        // 通知下一个节点开始抢锁
    }

    @Override
    public Condition newCondition() {
        return null;
    }

    public boolean casSwapState(int expect, int update) {
        return this.unsafe.compareAndSwapInt(this, this.stateAddress, expect, update);
    }

    public boolean casSwapHead(Node expect, Node update) {
        return this.unsafe.compareAndSwapObject(this,this.headAddress, expect, update);
    }

    public boolean casSwapTail(Node expect, Node update) {
        return this.unsafe.compareAndSwapObject(this,this.tailAddress, expect, update);
    }

    public void setState(int state) {
        this.state = state;
    }

    public void setCurrentThread(Thread currentThread) {
        this.currentThread = currentThread;
    }

    private boolean acquireQueued(Node node) {
        for (;;) {
            Node pred = node.pre;
            // cas结合线程阻塞
            if (pred == head && tryLock()) {
                // 把你自己变成头节点
                head = node;
                node.pre = null;
                return true;
            }

            // 循环处理node状态，只有前面为-1的时候，才返回true
            LockSupport.park();
            // 等待被唤醒
        }
    }

    /**
     * 自旋添加到队尾
     * @return
     */
    public Node addWaiter() {
        Node node = new Node(Thread.currentThread());

        Node pred = tail;
        if (pred != null) {
            node.pre = pred;
            if (casSwapTail(pred, node)) {
                pred.next = node;
                return node;
            }
        }
        enq(node);
        return node;
    }

    public void enq(Node node) {
        for (;;) {
            Node pred = tail;
            if (pred == null) {
                if (casSwapHead(null, EMPTY_NODE)) {
                    tail = head;
                }
            } else {
                node.pre = pred;
                if (casSwapTail(pred, node)) {
                    pred.next = node;
                    break;
                }
            }
        }
    }

    private class Node {
        // 节点状态
        private volatile int status;

        // 节点包含的线程
        private final Thread thread;

        // 后继节点
        private Node next;

        // 前驱节点
        private Node pre;

        public Node() {
            thread = null;
            next = null;
        }

        public Node(Thread thread) {
            this.thread = thread;
        }

        public void setNext(Node next) {
            this.next = next;
        }
    }

    private interface NodeStatus {
        int SINGNAL = -1;
        int CANCLED = -2;
    }

    public static void main(String[] args) throws Exception{
        try {
            int a = 1/0;
            File file = new File("d:/123.txt");
            if (!file.exists()) {
                file.createNewFile();
            }
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
    }
}
